package JasPerl::JSTL::Fmt::NumberFormat;

use 5.010;
use strict;
use warnings;

use Data::Dumper;

use JasPerl::JSTL::Fmt::CLDR;
use JasPerl::Util::Locale;

our $VERSION = 0.1;

my $CLDR_DECIMAL_FORMAT_PATH = "numbers/decimalFormats/standard/pattern";
my $CLDR_PERCENT_FORMAT_PATH = "numbers/percentFormats/standard/pattern";
my $CLDR_SYMBOLS = "numbers/symbols";

my $PATTERN_PARSER = do {
    use Regexp::Grammars 1.026;

    qr{
        <nocontext:>

         ^ <MATCH=Pattern> $

        <rule:Pattern>
            <pos=PositivePattern> (:? [;] <neg=NegativePattern> )?

        <rule:PositivePattern>
            <pre=Prefix> <num=Number> <suf=Suffix>

        <rule:NegativePattern>
            <pre=Prefix> <num=Number> <suf=Suffix>

        <rule:Number>
            <int=Integer> <exp=Exponent>?
          | <int=Integer> [.] <frac=Fraction> <exp=Exponent>?

        <rule:Integer>
            <[MATCH=MinGroup]>+ % [,]
          | <[MATCH=OptGroup]>+ % [,] (?: , <[MATCH=MinGroup]>+ % [,] )?
          | (:? <[MATCH=OptGroup]>+ % [,] , )? <[MATCH=IntGroup]> (?: , <[MATCH=MinGroup]>+ % [,] )?

        <rule:Fraction>
            <min=MinInteger>? <opt=OptInteger>?

        <rule:IntGroup>
            <opt=OptInteger> <min=MinInteger>

        <rule:OptGroup>
            <opt=OptInteger>

        <rule:MinGroup>
            <min=MinInteger>

        <token:OptInteger>
            ([#]+) <MATCH=(?{ length $CAPTURE })>

        <token:MinInteger>
            ([0]+) <MATCH=(?{ length $CAPTURE })>

        <token:Exponent>
            E (0+) <MATCH=(?{ length $CAPTURE })>

        <token:Prefix>
            [^0#,.]*

        <token:Suffix>
            [^0#,.]*

    }xms;
};

sub get_decimal_format {
    my ($class, $locale) = @_;
    $locale //= JasPerl::Util::Locale->get_default();
    my $cldr = JasPerl::JSTL::Fmt::CLDR->get_locale($locale);
    my $pattern = $cldr->find_node($CLDR_DECIMAL_FORMAT_PATH);
    return $class->new($pattern, $locale);
}

sub get_percent_format {
    my ($class, $locale) = @_;
    $locale //= JasPerl::Util::Locale->get_default();
    my $cldr = JasPerl::JSTL::Fmt::CLDR->get_locale($locale);
    my $pattern = $cldr->find_node($CLDR_DECIMAL_FORMAT_PATH);
    return $class->new($pattern, $locale);
}

sub get_currency_format {
    my ($class, $locale) = @_;
}

sub new {
    my ($class, $pattern, $locale) = @_;
    $locale //= JasPerl::Util::Locale->get_default();

    die "no pattern" unless defined $pattern;
    $pattern =~ $PATTERN_PARSER or die "'$pattern' does not match";

    my $minint = 0;
    my @ints = @{$/{pos}->{num}->{int}};
    foreach (@ints) {
        $minint += $_->{min} || 0;
    }
    my $minfrac = $/{pos}->{num}->{frac}->{min} || 0;
    my $group = ($/{pos}->{num}->{int}->[-1]->{min} || 0)
        + ($/{pos}->{num}->{int}->[-1]->{opt} || 0);

    my $cldr = JasPerl::JSTL::Fmt::CLDR->get_locale($locale);
    my $symbols = $cldr->find_node($CLDR_SYMBOLS);
#    warn Dumper($symbols);

    my $self = bless { pattern => $pattern, symbols => $symbols, locale => $locale }, $class;
    #$self->{group} = $group;
    $self->{minint} = $minint;
    $self->{minfrac} = $minfrac;
    warn "self=", Dumper($self);
    return $self;
}

sub clone {
    bless { %{$_[0]} }, ref $_[0];
}

sub get_currency {
}

sub set_currency {
}

sub get_minimum_integer_digits {
    return $_[0]->{minint};
}

sub set_minimum_integer_digits {
    $_[0]->{minint} = int $_[1];
}

sub get_maximum_integer_digits {
    return $_[0]->{maxint};
}

sub set_maximum_integer_digits {
    $_[0]->{maxint} = int $_[1];
}

sub get_minimum_fraction_digits {
    return $_[0]->{minfrac};
}

sub set_minimum_fraction_digits {
    $_[0]->{minfrac} = int $_[1];
}

sub get_maximum_fraction_digits {
    return $_[0]->{maxfrac};
}

sub set_maximum_fraction_digits {
    $_[0]->{maxfrac} = int $_[1];
}

sub is_grouping_used {
    return $_[0]->{group};
}

sub set_groupting_used {
    $_[0]->{group} = $_[1];
}

sub is_parse_integer_only {
}

sub set_parse_integer_only {
}

sub format {
    my ($self, $number) = @_;
    my ($int, $frac) = $number =~ /^(\d+)\D*(\d*)$/
        or die "Cannot parse number";
    warn "### number: $number $int $frac";
    if (length($int) < $self->{minint}) {
        $int = '0' x ($self->{minint} - length($int)) . $int;
    }
    if (length($frac) < $self->{minfrac}) {
        $frac .= '0' x ($self->{minfrac} - length($frac));
    }

    if ($self->is_grouping_used) {
        # TODO: split starting at end!
        $int = join($self->{symbols}->{group}, split(/(\d{3})/, $int));
        warn "### number: $number $int $frac";
    }

    if (length $frac) {
        return $int . $self->{symbols}->{decimal} . $frac;
    } else {
        return $int;
    }
}

sub parse {
    my ($self, $string) = @_;
    return 42;
}

1;
